--[[
   *** Tank Warnings ***
   
   Warning messages for tanks heavily inspired in Tankalyze
   
   mumbles Turalyon EU rui@ngen.org
   http://www.wowace.com/projects/tankwarnings
   svn://svn.wowace.com/wow/tankwarnings/mainline/trunk

   version v1.3
   60
]]--

local englishClass = select (2, UnitClass("player"))
if englishClass ~= "DRUID" and englishClass ~= "PALADIN" and englishClass ~= "WARRIOR" and englishClass ~= "DEATHKNIGHT" then return end

-- Addon Init
TankWarnings = LibStub("AceAddon-3.0"):NewAddon("TankWarnings", "AceConsole-3.0", "AceEvent-3.0", "LibSink-2.0")
local tw = TankWarnings
local AceDB = LibStub("AceDB-3.0")
local AceDBOptions = LibStub("AceDBOptions-3.0")
local db
local registry = LibStub("AceConfigRegistry-3.0")
local dialog = LibStub("AceConfigDialog-3.0")

-- Locale
local AceLocale = LibStub("AceLocale-3.0")
local L = AceLocale:GetLocale("TankWarnings")

-- Our class
tw.englishClass = englishClass

--  locals
local IsInInstance = IsInInstance
local UnitGUID = UnitGUID
local UnitLevel = UnitLevel
local UnitName = UnitName
local GetNumRaidMembers = GetNumRaidMembers
local SendChatMessage = SendChatMessage
local GetNumPartyMembers = GetNumPartyMembers
local GetSpellInfo = GetSpellInfo
local UnitBuff = UnitBuff
local IsRaidLeader = IsRaidLeader
local IsRaidOfficer = IsRaidOfficer

--[[ 
    Table with class spell ids to easily reference later the messages and
    settings on user options
]]--
tw.spellids = {
    ["WARRIOR"] = {
        resists = {
            [355] = "taunt",
            [1161] = "shout",
        },
        announcements = {
            [1161] = "shout",
            [871] = "shieldwall",
            [12975] = "laststand",
	    [55694] = "enraged",
        },
    },
    ["DRUID"] = {
        resists = {
            [6795] = "growl",
            [5209] = "roar",
        },
        announcements = {
            [5209] = "roar",
            [61336] = "survival",
            [22812] = "barkskin",
            [22842] = "frenzied",
	    [50334] = "berserk",
        },
    },
    ["PALADIN"] = {
        resists = {
            [31935] = "ashield",
            [31789] = "righteous",
            [62124] = "hor",
        },
        announcements = {
            [498] = "divine",
            [1022] = "hop",
            [633] = "loh",
            [1038] = "hos",
	    [31850] = "ardent",
	    [70940] = "guardian",
	    [86150] = "ancientkings",
        },
    },
    ["DEATHKNIGHT"] = {
        resists = {
	   [56222] = "darkcommand",
	   [49576] = "deathgrip",
        },
        announcements = {
	   [48792] = "ibf",
	   [48743] = "deathpact",
	   [42650] = "aotd",
	   [48707] = "ams",
	   [49028] = "drw",
	   [55233] = "vb",
        },
    },
}

--[[
    OnInitialize
    
    Function called by Ace3 uppon loading
    
    @return void
]]--
function tw:OnInitialize()
    db = AceDB:New("TankWarningsDB", self.defaults)
    self.db = db
    self.options.args.profile = AceDBOptions:GetOptionsTable(db)

    self:SetSinkStorage(self.db.profile.messages.sinkOptions)
   
    registry:RegisterOptionsTable("TankWarnings", tw.options)
    self:RegisterChatCommand("tw", function() dialog:Open("TankWarnings") end)
    self:RegisterChatCommand("tankwarnings", function() dialog:Open("TankWarnings") end)
    dialog:AddToBlizOptions("TankWarnings", "TankWarnings")
end

--[[
    OnEnable
    
    Function called by Ace3 when the addon is Enabled by the used
    
    @return void
]]--
function tw:OnEnable()
    self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end

--[[
    OnDisable
    
    Function called by Ace3 when the addon is Disabled by the used
    
    @return void
]]--
function tw:OnDisable()
end

--[[
    COMBAT_LOG_EVENT_UNFILTERED
    
    Function triggered when the evenet witht he same name is triggered to parse resists and announcements
    Read http://www.wowwiki.com/API_COMBAT_LOG_EVENT for more info
    
    @params string  event
    @params integer timestamp
    @params string  subevent
    @params integer srcGUID
    @params string  srcname
    @params integer srcflags
    @params integer dstGUID
    @params string  dstname
    @params integer dstflags
    @params integer spellID
    @params string  spellname
    @params integer spellschool
    @return void
]]--
function tw:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, subevent, srcGUID, srcname, srcflags, dstGUID, dstname, dstflags, spellID, spellname, spellschool, missType)
    -- If we should be disabled for PvP (Bg's or arenas) no point in continuing after this
    if self.db.profile.messages.disableinpvp and self:IsInPvP() then
        return
    end

    if UnitGUID("player") == srcGUID then
        -- Resists/immune
        if subevent == "SPELL_MISSED" then
            -- if this spell is not covered by our resists spell, return
            if not self.spellids[self.englishClass].resists[spellID] then return end
            
            local dbval = self.spellids[self.englishClass].resists[spellID]

            -- Resists
            if (missType ~= nil and (missType == "MISS" or missType == "RESIST")) then
                local level = UnitLevel("target")
                local guid = UnitGUID("target")
                
                if guid ~= dstGUID then level = "" end
                if level == -1 then level = L["Boss"] end

                message = self.db.profile.messages.resists[dbval]
                -- just in case if the user sets the message empty, don't if it will be nil or not
                if not message then return end
                message = string.gsub(string.gsub(message, "{t}", dstname), "{l}", level)
                self:Announce(message)
                
                -- no need to process this event anymore
                return
            end

            -- Immune
            if missType ~= nil and missType == "IMMUNE" and db.profile.messages.alertimmune then
                message = self.db.profile.messages.immunemessage
                -- just in case if the user sets the message empty, don't if it will be nil or not
                if not message then return end
                message = string.gsub(string.gsub(message, "{t}", dstname), "{s}", spellname)
                self:Announce(message)
                
                -- no need to process this event anymore
                return
            end
        end
        
        -- Announcements
        if subevent == "SPELL_CAST_SUCCESS" then
            -- if this spell is not covered by our announcements spell, return
            if not self.spellids[self.englishClass].announcements[spellID] then return end
            
            local dbval = self.spellids[self.englishClass].announcements[spellID]
            
            -- Process timer bars
            self:ProcessBarTimers(spellID)

            message = self.db.profile.messages.announcements[dbval]
            
            -- just in case if the user sets the message empty, don't if it will be nil or not
            if not message then return end
            
            -- if it's hand of protection, lay on hands or hand of sacrifice (no other way i know of about doing this without hardcoding the spellids here) we
            -- should want in which target was it
            if (spellID == 1022 or spellID == 633 or spellID == 1038) and dstname ~= nil then
                message = string.gsub(message, "{t}", dstname)
            end
            self:Announce(message)

            -- no need to process this anymore
            return
        end
    end
end

--[[
    Announce
    
    Announces through LibSink and/or Raid warning depending on user preferences the specified message
    
    @params string  message The message to be displayed, required
    @params string  target  Target name on which the ability was used or (in case of AoE abilities like aoe shouts) the one who got the resist
    @params integer level   The level of the target
    return void
]]--
function tw:Announce(message)
    if message == nil then return end

    -- Message output
    if self.db.profile.messages.sendraid then
        -- First check if our sink is sending to raid already, if it is, bail out no need to send this
        if self.db.profile.messages.sinkOptions.sink20OutputSink ~= "RaidWarning" then
            -- Check if were in a raid, if we are, check if we have permissions to send the message there
            if GetNumRaidMembers() > 0 then
                if self:IsPromoted() then
                    SendChatMessage(message, "RAID_WARNING")
                else
                    self:Print(L["Cannot send message to raid, not promoted"])
                end
            elseif GetNumPartyMembers() > 0 then -- in a party ? send to raid warning anyway, doesn't need promotion
                SendChatMessage(message, "RAID_WARNING")
            end
        end
    end
    
    -- Raid to party fallback hack, if the user has sink sending the messages to raid
    -- but he is in a party instead, falls back to party
    -- ticket #1 by Castnicke
    if self.db.profile.messages.sinkOptions.sink20OutputSink == "Channel" and self.db.profile.messages.sinkOptions.sink20ScrollArea == "Raid" then
        if GetNumRaidMembers() == 0 then
            -- Set the sink to temporarily be PARTY, doesn't get saved on user options
            self.db.profile.messages.sinkOptions.sink20ScrollArea = "Party"
            
            -- Send the message now so we can restore the setting after
            -- send it only if were on a party, if were not in a party then don't, restore the setting below and leave
            if GetNumPartyMembers() > 0 then
                self:Pour(message, 1, 0, 0, nil, 24, "OUTLINE", true)
            end
            
            -- set it back to raid or else if the user after leaving this party and joining a raid will still send to party
            -- so we need to keep the current working settings reflected on state of the configuration
            self.db.profile.messages.sinkOptions.sink20ScrollArea = "Raid"
            
            -- stop processing here so we don't get repeated messages and more useless elseif's etc
            return
        end
    end

    -- send our message through the sink
    self:Pour(message, 1, 0, 0, nil, 24, "OUTLINE", true)
end

--[[
    ProcessBarTimers
    
    Function to create timer bars using 3rd party addons like BigWigs displaying the time left on abilities used in announcements
    like Shield Wall, Last Stand, Challenging Shout etc
    For now, only supports BigWigs and requires Custom Bars module enabled (part of BigWigs_Extras addon)

    TODO: Test again with bigwigs and dbm they might have changed something in their API although I had no reports saying otherwise.
    
    @param integer skillid The skill id used in the announcement
    @return void
]]--
function tw:ProcessBarTimers(skillid)
    -- Get skill info
    local name, _, icon = GetSpellInfo(skillid)
    
    -- Find our buff to query it's duration to display the bar
    local timeleft = 0
    _, _, _, _, _, timeleft, _, _, _ = UnitBuff("player", name, true)

    -- something went wrong we can't find our buff....
    if timeleft == nil then return end
    
    -- does the buff last time enough for us to call a timer bar ?
    if timeleft < db.profile.announcements.bigwigs.mintime then return end

    -- Check which boss mod should we use to warn
    if BigWigsLoader and db.profile.announcements.bigwigs.enable then 
        message = string.format("%s %s - %s", timeleft, UnitName("player"), name)
        self:BigwigsBar(message) 
    end
    
    if DBM and db.profile.announcements.dbm.enable then 
        message = string.format("%s %s", UnitName("player"), name)
        self:DBMBar(timeleft, message, icon) 
    end
end

--[[
    BigwigsBar

    Triggers Bigwigs bars

    @param string message bigwigs bar message, same format as /bwcb or /bwlcb
    @return void
]]--
function tw:BigwigsBar(message)
    local sh = nil
    if db.profile.announcements.bigwigs.global then
       sh = _G["SlashCmdList"]["BWCB_SHORTHAND"]
    else
       sh = _G["SlashCmdList"]["BWLCB_SHORTHAND"]
    end
    if sh then sh(message) end
end

--[[
    DBMBar
]]--
function tw:DBMBar(timeleft, message, icon)
    -- Does the module exists ?
    if not DBT then
        -- warn the user it doesn't exist
        self:Print(L["Deadly bar timers not loaded"])
        return 
    end

    CustomBar = nil
    if db.profile.announcements.dbm.owngroup then
       CustomBar = DBT:New()
    else
       CustomBar = DBM.Bars
    end
       
    if CustomBar then
       CustomBar:CreateBar(timeleft, message, icon, nil, true)
    end
end

--[[
    Test
    
    Function called to test the announcement of messages from the configuration UI
    
    @return void
]]--
function tw:Test()
    self:Announce(string.gsub(string.gsub(L["Resist Test Message"], "{t}", UnitName("player")), "{l}", UnitLevel("player")))
    self:Announce(string.gsub(string.gsub(L["Resist Test Message"], "{t}", UnitName("player")), "{l}", UnitLevel("player")))
end

--[[
    IsPromoted
    
    Verifies if the user is raid leader or promoted to assistance in the raid
    
    @return boolean true if promoted or leader false otherwise
]]--
function tw:IsPromoted()
	return IsRaidLeader() or IsRaidOfficer() and true or nil
end

--[[
    IsInPvP
    
    Checks if the user is in Battleground or Arenas
    
    @return boolean true if in a bg or arena, false otherwise
]]--
function tw:IsInPvP()
    if (select(2, IsInInstance()) == "arena") or (select(2, IsInInstance()) == "pvp") then return true end
    return false
end

--[[
    FilterOptionsByClass
    
    Checks if the paramater option should be shown to the user or not depending on his class
    
    @params string class The class that the parameter should show to
    @return boolean Returns true if the class is not the same as the user class, false otherwise
]]--
function tw:FilterOptionsByClass(class)
    if tw.englishClass == class then
        return false
    end
    
    return true
end

--[[
    Configuration Options Table
]]--
tw.options = {
    type = "group",
    name = L["Tank Warnings"],
    args = {
        resists = {
            type = "group",
            name = L["Resists"],
            desc = L["Settings for resists"],
            order = 10,
            args = {
                taunt = {
                    type = "toggle",
                    name = L["Taunt"],
                    desc = L["Announces resisted taunts"],
                    get = function(info) return db.profile.resists.taunt end,
                    set = function(info, v) db.profile.resists.taunt = v end,
                    hidden = tw:FilterOptionsByClass("WARRIOR"),
                    width = "full",
                    order = 1,
                },
                shout = {
                    type = "toggle",
                    name = L["Challenging Shout"],
                    desc = L["Announces resisted challenging shouts"],
                    get = function(info) return db.profile.resists.shout end,
                    set = function(info, v) db.profile.resists.shout = v end,
                    hidden = tw:FilterOptionsByClass("WARRIOR"),
                    width = "full",
                    order = 2,
                },
                growl = {
                    type = "toggle",
                    name = L["Growl"],
                    desc = L["Announces resisted growls"],
                    get = function(info) return db.profile.resists.growl end,
                    set = function(info, v) db.profile.resists.growl = v end,
                    hidden = tw:FilterOptionsByClass("DRUID"),
                    width = "full",
                    order = 3,
                },
                roar = {
                    type = "toggle",
                    name = L["Challenging Roar"],
                    desc = L["Announces resisted challenging roars"],
                    get = function(info) return db.profile.resists.roar end,
                    set = function(info, v) db.profile.resists.roar = v end,
                    hidden = tw:FilterOptionsByClass("DRUID"),
                    width = "full",
                    order = 4,
                },
                hor = {
                    type = "toggle",
                    name = L["Hand of Reckoning"],
                    desc = L["Announces resisted Hand of Reckoning"],
                    get = function(info) return db.profile.resists.hor end,
                    set = function(info, v) db.profile.resists.hor = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 5,
                },
                righteous = {
                    type = "toggle",
                    name = L["Righteous Defense"],
                    desc = L["Announces resisted righteous defense"],
                    get = function(info) return db.profile.resists.roar end,
                    set = function(info, v) db.profile.resists.roar = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 6,
                },
                ashield = {
                    type = "toggle",
                    name = L["Avengers Shield"],
                    desc = L["Announces resisted avengers shield"],
                    get = function(info) return db.profile.resists.ashield end,
                    set = function(info, v) db.profile.resists.ashield = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 7,
                },
                darkcommand = {
                    type = "toggle",
                    name = L["Dark Command"],
                    desc = L["Announces resisted dark command"],
                    get = function(info) return db.profile.resists.darkcommand end,
                    set = function(info, v) db.profile.resists.darkcommand = v end,
                    hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                    width = "full",
                    order = 8,
                },
                deathgrip = {
                    type = "toggle",
                    name = L["Death Grip"],
                    desc = L["Announces resisted death grip"],
                    get = function(info) return db.profile.resists.deathgrip end,
                    set = function(info, v) db.profile.resists.deathgrip = v end,
                    hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                    width = "full",
                    order = 9,
                },
            },
        },
        announcements = {
            type = "group",
            name = L["Announcements"],
            desc = L["Settings for announcements"],
            order = 20,
            args = {
                shieldwall = {
                    type = "toggle",
                    name = L["Shield Wall"],
                    desc = L["Shield Wall"],
                    get = function(info) return db.profile.announcements.shieldwall end,
                    set = function(info, v) db.profile.announcements.shieldwall = v end,
                    hidden = tw:FilterOptionsByClass("WARRIOR"),
                    width = "full",
                    order = 1,
                },
                laststand = {
                    type = "toggle",
                    name = L["Last Stand"],
                    desc = L["Last Stand"],
                    get = function(info) return db.profile.announcements.laststand end,
                    set = function(info, v) db.profile.announcements.laststand = v end,
                    hidden = tw:FilterOptionsByClass("WARRIOR"),
                    width = "full",
                    order = 2,
                },
                shout = {
                    type = "toggle",
                    name = L["Challenging Shout"],
                    desc = L["Challenging Shout"],
                    get = function(info) return db.profile.announcements.shout end,
                    set = function(info, v) db.profile.announcements.shout = v end,
                    hidden = tw:FilterOptionsByClass("WARRIOR"),
                    width = "full",
                    order = 3,
                },
                enraged = {
                    type = "toggle",
                    name = L["Enraged Regeneration"],
                    desc = L["Enraged Regeneration"],
                    get = function(info) return db.profile.announcements.enraged end,
                    set = function(info, v) db.profile.announcements.enraged = v end,
                    hidden = tw:FilterOptionsByClass("WARRIOR"),
                    width = "full",
                    order = 4,
                },
                roar = {
                    type = "toggle",
                    name = L["Challenging Roar"],
                    desc = L["Challenging Roar"],
                    get = function(info) return db.profile.announcements.roar end,
                    set = function(info, v) db.profile.announcements.roar = v end,
                    hidden = tw:FilterOptionsByClass("DRUID"),
                    width = "full",
                    order = 5,
                },
                survival = {
                    type = "toggle",
                    name = L["Survival Instincts"],
                    desc = L["Survival Instincts"],
                    get = function(info) return db.profile.announcements.survival end,
                    set = function(info, v) db.profile.announcements.survival = v end,
                    hidden = tw:FilterOptionsByClass("DRUID"),
                    width = "full",
                    order = 6,
                },
                barkskin = {
                    type = "toggle",
                    name = L["Barkskin"],
                    desc = L["Barkskin"],
                    get = function(info) return db.profile.announcements.barkskin end,
                    set = function(info, v) db.profile.announcements.barkskin = v end,
                    hidden = tw:FilterOptionsByClass("DRUID"),
                    width = "full",
                    order = 7,
                },
                frenzied = {
                    type = "toggle",
                    name = L["Frenzied Regeneration"],
                    desc = L["Frenzied Regeneration"],
                    get = function(info) return db.profile.announcements.frenzied end,
                    set = function(info, v) db.profile.announcements.frenzied = v end,
                    hidden = tw:FilterOptionsByClass("DRUID"),
                    width = "full",
                    order = 8,
                },
                berserk = {
                    type = "toggle",
                    name = L["Berserk"],
                    desc = L["Berserk"],
                    get = function(info) return db.profile.announcements.berserk end,
                    set = function(info, v) db.profile.announcements.berserk = v end,
                    hidden = tw:FilterOptionsByClass("DRUID"),
                    width = "full",
                    order = 9,
                },
                divine = {
                    type = "toggle",
                    name = L["Divine Protection"],
                    desc = L["Divine Protection"],
                    get = function(info) return db.profile.announcements.divine end,
                    set = function(info, v) db.profile.announcements.divine = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 10,
                },
                hop = {
                    type = "toggle",
                    name = L["Hand of Protection"],
                    desc = L["Hand of Protection"],
                    get = function(info) return db.profile.announcements.hop end,
                    set = function(info, v) db.profile.announcements.hop = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 11,
                },
                hos = {
                    type = "toggle",
                    name = L["Hand of Sacrifice"],
                    desc = L["Hand of Sacrifice"],
                    get = function(info) return db.profile.announcements.hos end,
                    set = function(info, v) db.profile.announcements.hos = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 12,
                },
                loh = {
                    type = "toggle",
                    name = L["Lay on Hands"],
                    desc = L["Lay on Hands"],
                    get = function(info) return db.profile.announcements.loh end,
                    set = function(info, v) db.profile.announcements.loh = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 13,
                },
                ardent = {
                    type = "toggle",
                    name = L["Ardent Defender"],
                    desc = L["Ardent Defender"],
                    get = function(info) return db.profile.announcements.ardent end,
                    set = function(info, v) db.profile.announcements.ardent = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 14,
                },
                guardian = {
                    type = "toggle",
                    name = L["Divine Guardian"],
                    desc = L["Divine Guardian"],
                    get = function(info) return db.profile.announcements.guardian end,
                    set = function(info, v) db.profile.announcements.guardian = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 15,
                },
                ancientkings = {
                    type = "toggle",
                    name = L["Guardian of Ancient Kings"],
                    desc = L["Guardian of Ancient Kings"],
                    get = function(info) return db.profile.announcements.ancientkings end,
                    set = function(info, v) db.profile.announcements.ancientkings = v end,
                    hidden = tw:FilterOptionsByClass("PALADIN"),
                    width = "full",
                    order = 16,
                },
                ibf = {
                    type = "toggle",
                    name = L["Icebound Fortitude"],
                    desc = L["Icebound Fortitude"],
                    get = function(info) return db.profile.announcements.ibf end,
                    set = function(info, v) db.profile.announcements.ibf = v end,
                    hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                    width = "full",
                    order = 17,
                },
                aotd = {
                    type = "toggle",
                    name = L["Army of the Dead"],
                    desc = L["Army of the Dead"],
                    get = function(info) return db.profile.announcements.aotd end,
                    set = function(info, v) db.profile.announcements.aotd = v end,
                    hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                    width = "full",
                    order = 18,
                },
                ams = {
                    type = "toggle",
                    name = L["Anti-Magic Shell"],
                    desc = L["Anti-Magic Shell"],
                    get = function(info) return db.profile.announcements.ams end,
                    set = function(info, v) db.profile.announcements.ams = v end,
                    hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                    width = "full",
                    order = 19,
                },
		vb = {
                    type = "toggle",
                    name = L["Vampiric Blood"],
                    desc = L["Vampiric Blood"],
                    get = function(info) return db.profile.announcements.vb end,
                    set = function(info, v) db.profile.announcements.vb = v end,
                    hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                    width = "full",
                    order = 20,
		},				 
		drw = {
                    type = "toggle",
                    name = L["Dancing Rune Weapon"],
                    desc = L["Dancing Rune Weapon"],
                    get = function(info) return db.profile.announcements.drw end,
                    set = function(info, v) db.profile.announcements.drw = v end,
                    hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                    width = "full",
                    order = 21,
		},				 
		deathpact = {
                    type = "toggle",
                    name = L["Death Pact"],
                    desc = L["Death Pact"],
                    get = function(info) return db.profile.announcements.deathpact end,
                    set = function(info, v) db.profile.announcements.deathpact = v end,
                    hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                    width = "full",
                    order = 22,
		},				 
                headerbw = {
                    type = "header",
                    name = L["BigWigs Timers"],
                    width = "full",
                    order = 30,
                    hidden = function() if BigWigsLoader then return false else return true end end,
                },
                enablebw = {
                    type = "toggle",
                    name = L["Enable BigWigs Timer Bars"],
                    desc = L["Enable the display of BigWigs timer bars of your skills showing the time they last"],
                    get = function(info) return db.profile.announcements.bigwigs.enable end,
                    set = function(info, v) db.profile.announcements.bigwigs.enable = v end,
                    order = 31,
                    width = "full",
                    hidden = function() if BigWigsLoader then return false else return true end end,
                },
                globalbw = {
                    type = "toggle",
                    name = L["Global Timer"],
                    desc = L["Make the timer global, showing for everyone in the raid instead of local only showing to you"],
                    get = function(info) return db.profile.announcements.bigwigs.global end,
                    set = function(info, v) db.profile.announcements.bigwigs.global = v end,
                    order = 32,
                    width = "full",
                    hidden = function() if BigWigsLoader then return false else return true end end,
                },
                mintimebw = {
                    type = "range",
                    name = L["Minimum Skill Time"],
                    desc = L["Skills that last less than the minimum skill time will not show a timer bar, setting to 0 will always show"],
                    get = function(info) return db.profile.announcements.bigwigs.mintime end,
                    set = function(info,v) db.profile.announcements.bigwigs.mintime = v end,
                    order = 33,
                    width = "full",
                    min = 0,
                    max = 30,
                    step = 1,
                    hidden = function() if BigWigsLoader then return false else return true end end,
                },
                headerdbm = {
                    type = "header",
                    name = L["DBM Timers"],
                    width = "full",
                    order = 34,
                    hidden = function() if DBM then return false else return true end end,
                },
                enabledbm = {
                    type = "toggle",
                    name = L["Enable DBM Timer Bars"],
                    desc = L["Enable the display of DBM timer bars of your skills showing the time they last"],
                    get = function(info) return db.profile.announcements.dbm.enable end,
                    set = function(info, v) db.profile.announcements.dbm.enable = v end,
                    order = 35,
                    width = "full",
                    hidden = function() if DBM then return false else return true end end,
                },
                owngroupdbm = {
                    type = "toggle",
                    name = L["Own Bar Group"],
                    desc = L["Create the Bar in a custom bar group outside of normal bars"],
                    get = function(info) return db.profile.announcements.dbm.owngroup end,
                    set = function(info, v) db.profile.announcements.dbm.owngroup = v end,
                    order = 36,
                    width = "full",
                    hidden = function() if DBM then return false else return true end end,
                },
                mintimedbm = {
                    type = "range",
                    name = L["Minimum Skill Time"],
                    desc = L["Skills that last less than the minimum skill time will not show a timer bar, setting to 0 will always show"],
                    get = function(info) return db.profile.announcements.dbm.mintime end,
                    set = function(info,v) db.profile.announcements.dbm.mintime = v end,
                    order = 37,
                    width = "full",
                    min = 0,
                    max = 30,
                    step = 1,
                    hidden = function() if DBM then return false else return true end end,
                },
            },
        },
        messages = {
            type = "group",
            name = L["Messages"],
            args = {
                test = {
                    type = "execute",
                    name = L["Test"],
                    desc = L["Send test messages with current settings"],
                    func = function() tw:Test() end,
                    order = 1,
                    width = "full"
                },
                disableinpvp = {
                    type = "toggle",
                    name = L["Disable in PvP"],
                    desc = L["Disable when player is in Battlegrounds/Arenas"],
                    get = function(info) return db.profile.messages.disableinpvp end,
                    set = function(info, v) db.profile.message.disableinpvp = v end,
                    order = 2,
                    width = "full",
                },
                sendraid = {
                    type = "toggle",
                    name = L["Send messages to raid warning regardless"],
                    desc = L["Displays the messages in raid warning regardles of your output config, usefull if you choose to output to somewhere else that is not Raid Warning"],
                    get = function(info) return db.profile.messages.sendraid end,
                    set = function(info, v) db.profile.messages.sendraid = v end,
                    order = 3,
                    width = "full",
                },
                alertimmune = {
                    type = "toggle",
                    name = L["Warn when immune"],
                    desc = L["Warn when the NPC is immune to your ability"],
                    get = function(info) return db.profile.messages.alertimmune end,
                    set = function(info, v) db.profile.messages.alertimmune = v end,
                    order = 4,
                    width = "full",
                },
                immunemessage = {
                    type = "input",
                    name = L["Immune Message"],
                    desc = L["MessagesInfoImmune"],
                    get = function(info) return db.profile.messages.immunemessage end,
                    set = function(info, v) db.profile.messages.immunemessage = v end,
                    width = "full",
                    order = 5,
                    disabled = function() return not db.profile.messages.alertimmune end,
                },
                output = tw:GetSinkAce3OptionsDataTable(),
                resists = {
                    type = "group",
                    name = L["Resists Messages"],
                    desc = L["Message settings for resists"],
                    order = 10,
                    args = {
                        taunt = {
                            type = "input",
                            name = L["Taunt"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.resists.taunt end,
                            set = function(info, v) db.profile.messages.resists.taunt = v end,
                            hidden = tw:FilterOptionsByClass("WARRIOR"),
                            width = "full",
                            order = 1,
                        },
                        shout = {
                            type = "input",
                            name = L["Challenging Shout"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.resists.shout end,
                            set = function(info, v) db.profile.messages.resists.shout = v end,
                            hidden = tw:FilterOptionsByClass("WARRIOR"),
                            width = "full",
                            order = 2,
                        },
                        growl = {
                            type = "input",
                            name = L["Growl"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.resists.growl end,
                            set = function(info, v) db.profile.messages.resists.growl = v end,
                            hidden = tw:FilterOptionsByClass("DRUID"),
                            width = "full",
                            order = 3,
                        },
                        roar = {
                            type = "input",
                            name = L["Challenging Roar"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.resists.roar end,
                            set = function(info, v) db.profile.messages.resists.roar = v end,
                            hidden = tw:FilterOptionsByClass("DRUID"),
                            width = "full",
                            order = 4,
                        },
                        righteous = {
                            type = "input",
                            name = L["Righteous Defense"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.resists.righteous end,
                            set = function(info, v) db.profile.messages.resists.righteous = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 5,
                        },
                        ashield = {
                            type = "input",
                            name = L["Avengers Shield"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.resists.ashield end,
                            set = function(info, v) db.profile.messages.resists.ashield = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 6,
                        },
                        hor = {
                            type = "input",
                            name = L["Hand of Reckoning"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.resists.hor end,
                            set = function(info, v) db.profile.messages.resists.hor = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 7,
                        },
                        darkcommand = {
                            type = "input",
                            name = L["Dark Command"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.resists.darkcommand end,
                            set = function(info, v) db.profile.messages.resists.darkcommand = v end,
                            hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                            width = "full",
                            order = 8,
                        },
                        deathgrip = {
                            type = "input",
                            name = L["Death Grip"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.resists.deathgrip end,
                            set = function(info, v) db.profile.messages.resists.deathgrip = v end,
                            hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                            width = "full",
                            order = 9,
                        },
                    },
                },
                announcements = {
                    type = "group",
                    name = L["Announcement Messages"],
                    desc = L["Message settings for announcements"],
                    order = 10,
                    args = {
                        shieldwall = {
                            type = "input",
                            name = L["Shield Wall"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.shieldwall end,
                            set = function(info, v) db.profile.messages.announcements.shieldwall = v end,
                            hidden = tw:FilterOptionsByClass("WARRIOR"),
                            width = "full",
                            order = 1,
                        },
                        laststand = {
                            type = "input",
                            name = L["Last Stand"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.laststand end,
                            set = function(info, v) db.profile.messages.announcements.laststand = v end,
                            hidden = tw:FilterOptionsByClass("WARRIOR"),
                            width = "full",
                            order = 2,
                        },
                        shout = {
                            type = "input",
                            name = L["Challenging Shout"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.shout end,
                            set = function(info, v) db.profile.messages.announcements.shout = v end,
                            hidden = tw:FilterOptionsByClass("WARRIOR"),
                            width = "full",
                            order = 3,
                        },
                        enraged = {
                            type = "input",
                            name = L["Enraged Regeneration"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.enraged end,
                            set = function(info, v) db.profile.messages.announcements.enraged = v end,
                            hidden = tw:FilterOptionsByClass("WARRIOR"),
                            width = "full",
                            order = 4,
                        },
                        roar = {
                            type = "input",
                            name = L["Challenging Roar"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.roar end,
                            set = function(info, v) db.profile.messages.announcements.roar = v end,
                            hidden = tw:FilterOptionsByClass("DRUID"),
                            width = "full",
                            order = 5,
                        },
                        survival = {
                            type = "input",
                            name = L["Survival Instincts"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.survival end,
                            set = function(info, v) db.profile.messages.announcements.survival = v end,
                            hidden = tw:FilterOptionsByClass("DRUID"),
                            width = "full",
                            order = 6,
                        },
                        barkskin = {
                            type = "input",
                            name = L["Barkskin"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.barkskin end,
                            set = function(info, v) db.profile.messages.announcements.barkskin = v end,
                            hidden = tw:FilterOptionsByClass("DRUID"),
                            width = "full",
                            order = 7,
                        },
                        frenzied = {
                            type = "input",
                            name = L["Frenzied Regeneration"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.frenzied end,
                            set = function(info, v) db.profile.messages.announcements.frenzied = v end,
                            hidden = tw:FilterOptionsByClass("DRUID"),
                            width = "full",
                            order = 8,
                        },
                        berserk = {
                            type = "input",
                            name = L["Berserk"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.berserk end,
                            set = function(info, v) db.profile.messages.announcements.berserk = v end,
                            hidden = tw:FilterOptionsByClass("DRUID"),
                            width = "full",
                            order = 9,
                        },
                        divine = {
                            type = "input",
                            name = L["Divine Protection"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.divine end,
                            set = function(info, v) db.profile.messages.announcements.divine = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 10,
                        },
                        hop = {
                            type = "input",
                            name = L["Hand of Protection"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.announcements.hop end,
                            set = function(info, v) db.profile.messages.announcements.hop = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 11,
                        },
                        hos = {
                            type = "input",
                            name = L["Hand of Sacrifice"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.announcements.hos end,
                            set = function(info, v) db.profile.messages.announcements.hos = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 12,
                        },
                        loh = {
                            type = "input",
                            name = L["Lay on Hands"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.announcements.loh end,
                            set = function(info, v) db.profile.messages.announcements.loh = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 13,
                        },
                        ardent = {
                            type = "input",
                            name = L["Ardent Defender"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.announcements.ardent end,
                            set = function(info, v) db.profile.messages.announcements.ardent = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 14,
                        },
                        guardian = {
                            type = "input",
                            name = L["Divine Guardian"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.announcements.guardian end,
                            set = function(info, v) db.profile.messages.announcements.guardian = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 15,
                        },
                        ancientkings = {
                            type = "input",
                            name = L["Guardian of Ancient Kings"],
                            desc = L["MessagesInfo"],
                            get = function(info) return db.profile.messages.announcements.ancientkings end,
                            set = function(info, v) db.profile.messages.announcements.ancientkings = v end,
                            hidden = tw:FilterOptionsByClass("PALADIN"),
                            width = "full",
                            order = 16,
                        },
                        ibf = {
                            type = "input",
                            name = L["Icebound Fortitude"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.ibf end,
                            set = function(info, v) db.profile.messages.announcements.ibf = v end,
                            hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                            width = "full",
                            order = 17,
                        },
                        aotd = {
                            type = "input",
                            name = L["Army of the Dead"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.aotd end,
                            set = function(info, v) db.profile.messages.announcements.aotd = v end,
                            hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                            width = "full",
                            order = 18,
                        },
                        ams = {
                            type = "input",
                            name = L["Anti-Magic Shell"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.ams end,
                            set = function(info, v) db.profile.messages.announcements.ams = v end,
                            hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                            width = "full",
                            order = 19,
                        },
			vb = {
                            type = "input",
                            name = L["Vampiric Blood"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.vb end,
                            set = function(info, v) db.profile.messages.announcements.vb = v end,
                            hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                            width = "full",
                            order = 20,
			},
                        deathpact = {
                            type = "input",
                            name = L["Death Pact"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.deathpact end,
                            set = function(info, v) db.profile.messages.announcements.deathpact = v end,
                            hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                            width = "full",
                            order = 21,
                        },
                        drw = {
                            type = "input",
                            name = L["Dancing Rune Weapon"],
                            desc = L["MessagesInfoNoTarget"],
                            get = function(info) return db.profile.messages.announcements.drw end,
                            set = function(info, v) db.profile.messages.announcements.drw = v end,
                            hidden = tw:FilterOptionsByClass("DEATHKNIGHT"),
                            width = "full",
                            order = 22,
                        },
                    },
                },
            },
        },
    },
}

--[[
    Default Values
]]--
tw.defaults = {
   profile = {
      resists = {
	 taunt = true,
	 shout = true,
	 growl = true,
	 roar = true,
	 ashield = true,
	 righteous = true,
	 hor = true,
	 darkcommand = true,
	 deathgrip = true,
	 messages = {
	 }
      },
      announcements = {
	 shout = true,
	 shieldwall = true,
	 laststand = true,
	 enraged = true,
	 roar = true,
	 survival = true,
	 barkskin = true,
	 frenzied = true,
	 berserk = true,
	 divine = true,
	 hop = true,
	 loh = true,
	 hos = true,
	 ardent = true,
	 guardian = true,
	 ancientkings = true,
	 ibf = true,
	 deathpact = true,
	 aotd = true,
	 ams = true,
	 drw = true,
	 vb = true,
	 bigwigs = {
	    enable = true,
	    global = true,
	    mintime = 5,
	 },
	 dbm = {
	    enable = true,
	    owngroup = false,
	    mintime = 5,
	 },
      },
      messages = {
	 disableinpvp = true,
	 sendraid = true,
	 sinkOptions = {},
	 alertimmune = true,
	 immunemessage = L["ImmuneMessage"],
	 resists = {
	    taunt = L["TauntMessage"],
	    shout = L["ShoutMessage"],
	    growl = L["GrowlMessage"],
	    roar = L["RoarMessage"],
	    ashield = L["AvengersShieldMessage"],
	    righteous = L["RighteousMessage"],
	    hor = L["HandOfReckoningMessage"],
	    darkcommand = L["DarkCommandMessage"],
	    deathgrip = L["DeathGripMessage"],
	 },
	 announcements = {
	    shout = L["ChallengingShoutMessage"],
	    shieldwall = L["ShieldWallMessage"],
	    laststand = L["LastStandMessage"],
	    enraged = L["EnragedRegenerationMessage"],
	    roar = L["ChallengingRoarMessage"],
	    survival = L["SurvivalInstinctsMessage"],
	    barkskin = L["BarkskinMessage"],
	    frenzied = L["FrenziedMessage"],
	    berserk = L["BerserkMessage"],
	    divine = L["DivineProtectionMessage"],
	    hop = L["HandOfProtectionMessage"],
	    loh = L["LayOnHandsMessage"],            
	    hos = L["HandOfSacrificeMessage"],
	    ardent = L["ArdentDefenderMessage"],
	    guardian = L["DivineGuardianMessage"],
	    ancientkings = L["GuardianofAncientKingsMessage"],
	    ibf = L["IceboundFortitudeMessage"],
	    deathpact = L["DeathPactMessage"],
	    aotd = L["ArmyOfTheDeadMessage"],
	    ams = L["AntiMagicShellMessage"],
	    vb = L["VampiricBloodMessage"],
	    drw = L["DancingRuneWeaponMessage"],
	 },
      },
   },
}
